//
//  QRCodeViewController.swift
//  WBDemo
//
//  Created by Meng on 17/1/22.
//  Copyright © 2017年 demo. All rights reserved.
//

import UIKit
import AVFoundation

class QRCodeViewController: UIViewController, UITabBarDelegate, AVCaptureMetadataOutputObjectsDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    @IBOutlet weak var customContainerView: UIView!
    
    @IBOutlet weak var tabBar: UITabBar!
    
    
    @IBOutlet weak var qrcodeTopConstraint: NSLayoutConstraint!
    
    @IBOutlet weak var contentViewHeightConstraint: NSLayoutConstraint!
    
    
    @IBOutlet weak var qrcodeImageView: UIImageView!
    
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        tabBar.selectedItem = tabBar.items?.first
        tabBar.delegate = self
        startScanQRCode()
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        startAnimation()
    }
    
    @IBAction func closeAction(_ sender: Any) {
        dismiss(animated: true, completion: nil)
    }
    
    @IBAction func photoAlbum(_ sender: UIBarButtonItem) {
        if !UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
            return
        }
        let picker = UIImagePickerController()
        picker.delegate = self
        present(picker, animated: true, completion: nil)
        
    }
    
    
    private func startAnimation() {
        qrcodeTopConstraint.constant = -contentViewHeightConstraint.constant
        view.layoutIfNeeded()
        // 在Swift中一般情况下不用写self, 也不推荐我们写self
        // 一般情况下只有需要区分两个变量, 或者在闭包中访问外界属性才需要加上self
        // 优点可以提醒程序员主动思考当前self会不会形成循环引用
        UIView.animate(withDuration: 2.0) {
            UIView.setAnimationRepeatCount(MAXFLOAT)
            self.qrcodeTopConstraint.constant = self.contentViewHeightConstraint.constant
            self.view.layoutIfNeeded()
        }
    }
    
    private func startScanQRCode() {
        if !session.canAddInput(input) {
            return
        }
        if !session.canAddOutput(output) {
            return
        }
        session.addInput(input)
        session.addOutput(output)
        output.metadataObjectTypes = output.availableMetadataObjectTypes
        output.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
        view.layer.insertSublayer(previewLayer, at: 0)
        previewLayer.frame = view.bounds
        //添加容器图层
        view.layer.addSublayer(containerLayer)
        containerLayer.frame = view.bounds
        session.startRunning()
    }
    
    // MARK: - UITabBarDelegate
    func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
        contentViewHeightConstraint.constant = (item.tag == 1) ? 150 : 200
        view.layoutIfNeeded()
        qrcodeImageView.layer.removeAllAnimations()
        startAnimation()
    }
    
    // MARK: - 懒加载
    private lazy var input: AVCaptureDeviceInput? = {
        let device: AVCaptureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
        return try? AVCaptureDeviceInput(device: device)
    }()
    private lazy var session: AVCaptureSession = AVCaptureSession()
    private lazy var output: AVCaptureMetadataOutput = {
        let out = AVCaptureMetadataOutput()
        // 设置输出对象解析数据时感兴趣的范围
        // 默认值是 CGRect(x: 0, y: 0, width: 1, height: 1)
        // 通过对这个值的观察, 我们发现传入的是比例
        // 注意: 参照是以横屏的左上角作为, 而不是以竖屏
        //        out.rectOfInterest = CGRect(x: 0, y: 0, width: 0.5, height: 0.5)
        
        // 1.获取屏幕的frame
        let viewRect = self.view.frame
        // 2.获取扫描容器的frame
        let containerRect = self.customContainerView.frame
        let x = containerRect.origin.y / viewRect.height;
        let y = containerRect.origin.x / viewRect.width;
        let width = containerRect.height / viewRect.height;
        let height = containerRect.width / viewRect.width;
//        MYLog(viewRect)
//        MYLog(containerRect)
//        MYLog(x)
//        MYLog(y)
//        MYLog(width)
//        MYLog(height)
        out.rectOfInterest = CGRect(x: x, y: y, width: width, height: height)
        
        return out
    }()
    private lazy var previewLayer: AVCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: self.session)
    /// 专门用于保存描边的图层
    private lazy var containerLayer: CALayer = CALayer()
    
    // MARK: - AVCaptureMetadataOutputObjectsDelegate
    func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
        MYLog(metadataObjects.last)
        clearLayers()
        
        // 2.拿到扫描到的数据
        guard let metadata = metadataObjects.last as? AVMetadataObject else
        {
            return
        }
        // 转换前: corners { 0.3,0.7 0.5,0.7 0.5,0.4 0.3,0.4 }
        // 转换后: corners { 40.0,230.3 30.9,403.9 216.5,416.3 227.1,244.2 }
        // 通过预览图层将corners值转换为我们能识别的类型
        let objc = previewLayer.transformedMetadataObject(for: metadata)
        
        //        NJLog((objc as! AVMetadataMachineReadableCodeObject).corners)
        
        // 2.对扫描到的二维码进行描边
        drawLines(objc as! AVMetadataMachineReadableCodeObject)
    }
    /// 绘制描边
    private func drawLines(_ objc: AVMetadataMachineReadableCodeObject)
    {
        
        // 0.安全校验
        guard let array = objc.corners else
        {
            return
        }
        
        // 1.创建图层, 用于保存绘制的矩形
        let layer = CAShapeLayer()
        layer.lineWidth = 2
        layer.strokeColor = UIColor.green.cgColor
        layer.fillColor = UIColor.clear.cgColor
        
        // 2.创建UIBezierPath, 绘制矩形
        let path = UIBezierPath()
        var index = 0
        var point = CGPoint(dictionaryRepresentation: (array[index] as! CFDictionary))
        index += 1
        // 2.1将起点移动到某一个点
        path.move(to: point!)
        // 2.2连接其它线段
        while index < array.count
        {
            point = CGPoint(dictionaryRepresentation: (array[index] as! CFDictionary))
            path.addLine(to: point!)
            index += 1
        }
        // 2.3关闭路径
        path.close()
        
        layer.path = path.cgPath
        // 3.将用于保存矩形的图层添加到界面上
        containerLayer.addSublayer(layer)
    }
    
    /// 清空描边
    private func clearLayers()
    {
        guard let subLayers = containerLayer.sublayers else
        {
            return
        }
        for layer in subLayers
        {
            layer.removeFromSuperlayer()
        }
    }
    
    // MARK: - UIImagePickerControllerDelegate
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
        guard let image = info[UIImagePickerControllerOriginalImage] as? UIImage else {
            return
        }
        // 创建探测器
        guard let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy : CIDetectorAccuracyHigh]) else {
            return
        }
        
        // 利用探测器识别图片
        guard let ciImage = CIImage(image: image) else {
            return
        }
        
        let results = detector.features(in: ciImage)
        // 取出识别出的数据
        for item in results {
            MYLog((item as! CIQRCodeFeature).messageString)
        }
    }
    
    
}

